<div class="body" role="main">
            
  <div class="section" id="tweaking">
<h1>Tweaking<a class="headerlink" href="#tweaking" title="Permalink to this headline">¶</a></h1>
<div class="section" id="using-the-logging-module">
<span id="usinglogging"></span><h2>Using the Logging Module<a class="headerlink" href="#using-the-logging-module" title="Permalink to this headline">¶</a></h2>
<p>We have already taken a brief look at the <em>ns-3</em> logging module while
going over the <code class="docutils literal notranslate"><span class="pre">first.cc</span></code> script.  We will now take a closer look and
see what kind of use-cases the logging subsystem was designed to cover.</p>
<div class="section" id="logging-overview">
<h3>Logging Overview<a class="headerlink" href="#logging-overview" title="Permalink to this headline">¶</a></h3>
<p>Many large systems support some kind of message logging facility, and
<em>ns-3</em> is not an exception.  In some cases, only error messages are
logged to the “operator console” (which is typically <code class="docutils literal notranslate"><span class="pre">stderr</span></code> in Unix-
based systems).  In other systems, warning messages may be output as well as
more detailed informational messages.  In some cases, logging facilities are
used to output debug messages which can quickly turn the output into a blur.</p>
<p><em>ns-3</em> takes the view that all of these verbosity levels are useful
and we provide a selectable, multi-level approach to message logging.  Logging
can be disabled completely, enabled on a component-by-component basis, or
enabled globally; and it provides selectable verbosity levels.  The
<em>ns-3</em> log module provides a straightforward, relatively easy to use
way to get useful information out of your simulation.</p>
<p>You should understand that we do provide a general purpose mechanism —
tracing — to get data out of your models which should be preferred for
simulation output (see the tutorial section Using the Tracing System for
more details on our tracing system).  Logging should be preferred for
debugging information, warnings, error messages, or any time you want to
easily get a quick message out of your scripts or models.</p>
<p>There are currently seven levels of log messages of increasing verbosity
defined in the system.</p>
<ul class="simple">
<li>LOG_ERROR — Log error messages (associated macro: NS_LOG_ERROR);</li>
<li>LOG_WARN — Log warning messages (associated macro: NS_LOG_WARN);</li>
<li>LOG_DEBUG — Log relatively rare, ad-hoc debugging messages
(associated macro: NS_LOG_DEBUG);</li>
<li>LOG_INFO — Log informational messages about program progress
(associated macro: NS_LOG_INFO);</li>
<li>LOG_FUNCTION — Log a message describing each function called
(two associated macros: NS_LOG_FUNCTION, used for member functions,
and NS_LOG_FUNCTION_NOARGS, used for static functions);</li>
<li>LOG_LOGIC – Log messages describing logical flow within a function
(associated macro: NS_LOG_LOGIC);</li>
<li>LOG_ALL — Log everything mentioned above (no associated macro).</li>
</ul>
<p>For each LOG_TYPE there is also LOG_LEVEL_TYPE that, if used, enables
logging of all the levels above it in addition to it’s level.  (As a
consequence of this, LOG_ERROR and LOG_LEVEL_ERROR and also LOG_ALL
and LOG_LEVEL_ALL are functionally equivalent.)  For example,
enabling LOG_INFO will only enable messages provided by NS_LOG_INFO macro,
while enabling LOG_LEVEL_INFO will also enable messages provided by
NS_LOG_DEBUG, NS_LOG_WARN and NS_LOG_ERROR macros.</p>
<p>We also provide an unconditional logging macro that is always displayed,
irrespective of logging levels or component selection.</p>
<ul class="simple">
<li>NS_LOG_UNCOND – Log the associated message unconditionally (no associated
log level).</li>
</ul>
<p>Each level can be requested singly or cumulatively; and logging can be set
up using a shell environment variable (NS_LOG) or by logging system function
call.  As was seen earlier in the tutorial, the logging system has Doxygen
documentation and now would be a good time to peruse the Logging Module
documentation if you have not done so.</p>
<p>Now that you have read the documentation in great detail, let’s use some of
that knowledge to get some interesting information out of the
<code class="docutils literal notranslate"><span class="pre">scratch/myfirst.cc</span></code> example script you have already built.</p>
</div>
<div class="section" id="enabling-logging">
<h3>Enabling Logging<a class="headerlink" href="#enabling-logging" title="Permalink to this headline">¶</a></h3>
<p>Let’s use the NS_LOG environment variable to turn on some more logging, but
first, just to get our bearings, go ahead and run the last script just as you
did previously,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run scratch/myfirst
</pre></div>
</div>
<p>You should see the now familiar output of the first <em>ns-3</em> example
program</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.413s<span class="o">)</span>
Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
</pre></div>
</div>
<p>It turns out that the “Sent” and “Received” messages you see above are
actually logging messages from the <code class="docutils literal notranslate"><span class="pre">UdpEchoClientApplication</span></code> and
<code class="docutils literal notranslate"><span class="pre">UdpEchoServerApplication</span></code>.  We can ask the client application, for
example, to print more information by setting its logging level via the
NS_LOG environment variable.</p>
<p>I am going to assume from here on that you are using an sh-like shell that uses
the”VARIABLE=value” syntax.  If you are using a csh-like shell, then you
will have to convert my examples to the “setenv VARIABLE value” syntax
required by those shells.</p>
<p>Right now, the UDP echo client application is responding to the following line
of code in <code class="docutils literal notranslate"><span class="pre">scratch/myfirst.cc</span></code>,</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">LogComponentEnable</span><span class="p">(</span><span class="s">"UdpEchoClientApplication"</span><span class="p">,</span> <span class="n">LOG_LEVEL_INFO</span><span class="p">);</span>
</pre></div>
</div>
<p>This line of code enables the <code class="docutils literal notranslate"><span class="pre">LOG_LEVEL_INFO</span></code> level of logging.  When
we pass a logging level flag, we are actually enabling the given level and
all lower levels.  In this case, we have enabled <code class="docutils literal notranslate"><span class="pre">NS_LOG_INFO</span></code>,
<code class="docutils literal notranslate"><span class="pre">NS_LOG_DEBUG</span></code>, <code class="docutils literal notranslate"><span class="pre">NS_LOG_WARN</span></code> and <code class="docutils literal notranslate"><span class="pre">NS_LOG_ERROR</span></code>.  We can
increase the logging level and get more information without changing the
script and recompiling by setting the NS_LOG environment variable like this:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">export</span> <span class="nv">NS_LOG</span><span class="o">=</span><span class="nv">UdpEchoClientApplication</span><span class="o">=</span>level_all
</pre></div>
</div>
<p>This sets the shell environment variable <code class="docutils literal notranslate"><span class="pre">NS_LOG</span></code> to the string,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">UdpEchoClientApplication</span><span class="o">=</span>level_all
</pre></div>
</div>
<p>The left hand side of the assignment is the name of the logging component we
want to set, and the right hand side is the flag we want to use.  In this case,
we are going to turn on all of the debugging levels for the application.  If
you run the script with NS_LOG set this way, the <em>ns-3</em> logging
system will pick up the change and you should see the following output:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.404s<span class="o">)</span>
UdpEchoClientApplication:UdpEchoClient<span class="o">()</span>
UdpEchoClientApplication:SetDataSize<span class="o">(</span><span class="m">1024</span><span class="o">)</span>
UdpEchoClientApplication:StartApplication<span class="o">()</span>
UdpEchoClientApplication:ScheduleTransmit<span class="o">()</span>
UdpEchoClientApplication:Send<span class="o">()</span>
Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
UdpEchoClientApplication:HandleRead<span class="o">(</span>0x6241e0, 0x624a20<span class="o">)</span>
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
UdpEchoClientApplication:StopApplication<span class="o">()</span>
UdpEchoClientApplication:DoDispose<span class="o">()</span>
UdpEchoClientApplication:~UdpEchoClient<span class="o">()</span>
</pre></div>
</div>
<p>The additional debug information provided by the application is from
the NS_LOG_FUNCTION level.  This shows every time a function in the application
is called during script execution.  Generally, use of (at least)
NS_LOG_FUNCTION(this) in member functions is preferred. Use
NS_LOG_FUNCTION_NOARGS() only in static functions.  Note, however, that there
are no requirements in the <em>ns-3</em> system that models must support any particular
logging  functionality.  The decision regarding how much information is logged
is left to the individual model developer.  In the case of the echo
applications, a good deal of log output is available.</p>
<p>You can now see a log of the function calls that were made to the application.
If you look closely you will notice a single colon between the string
<code class="docutils literal notranslate"><span class="pre">UdpEchoClientApplication</span></code> and the method name where you might have
expected a C++ scope operator (<code class="docutils literal notranslate"><span class="pre">::</span></code>).  This is intentional.</p>
<p>The name is not actually a class name, it is a logging component name.  When
there is a one-to-one correspondence between a source file and a class, this
will generally be the class name but you should understand that it is not
actually a class name, and there is a single colon there instead of a double
colon to remind you in a relatively subtle way to conceptually separate the
logging component name from the class name.</p>
<p>It turns out that in some cases, it can be hard to determine which method
actually generates a log message.  If you look in the text above, you may
wonder where the string “<code class="docutils literal notranslate"><span class="pre">Received</span> <span class="pre">1024</span> <span class="pre">bytes</span> <span class="pre">from</span> <span class="pre">10.1.1.2</span></code>” comes
from.  You can resolve this by OR’ing the <code class="docutils literal notranslate"><span class="pre">prefix_func</span></code> level into the
<code class="docutils literal notranslate"><span class="pre">NS_LOG</span></code> environment variable.  Try doing the following,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">export</span> <span class="s1">'NS_LOG=UdpEchoClientApplication=level_all|prefix_func'</span>
</pre></div>
</div>
<p>Note that the quotes are required since the vertical bar we use to indicate an
OR operation is also a Unix pipe connector.</p>
<p>Now, if you run the script you will see that the logging system makes sure
that every message from the given log component is prefixed with the component
name.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.417s<span class="o">)</span>
UdpEchoClientApplication:UdpEchoClient<span class="o">()</span>
UdpEchoClientApplication:SetDataSize<span class="o">(</span><span class="m">1024</span><span class="o">)</span>
UdpEchoClientApplication:StartApplication<span class="o">()</span>
UdpEchoClientApplication:ScheduleTransmit<span class="o">()</span>
UdpEchoClientApplication:Send<span class="o">()</span>
UdpEchoClientApplication:Send<span class="o">()</span>: Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
UdpEchoClientApplication:HandleRead<span class="o">(</span>0x6241e0, 0x624a20<span class="o">)</span>
UdpEchoClientApplication:HandleRead<span class="o">()</span>: Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
UdpEchoClientApplication:StopApplication<span class="o">()</span>
UdpEchoClientApplication:DoDispose<span class="o">()</span>
UdpEchoClientApplication:~UdpEchoClient<span class="o">()</span>
</pre></div>
</div>
<p>You can now see all of the messages coming from the UDP echo client application
are identified as such.  The message “Received 1024 bytes from 10.1.1.2” is
now clearly identified as coming from the echo client application.  The
remaining message must be coming from the UDP echo server application.  We
can enable that component by entering a colon separated list of components in
the NS_LOG environment variable.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">export</span> <span class="s1">'NS_LOG=UdpEchoClientApplication=level_all|prefix_func:</span>
<span class="s1">               UdpEchoServerApplication=level_all|prefix_func'</span>
</pre></div>
</div>
<p>Warning:  You will need to remove the newline after the <code class="docutils literal notranslate"><span class="pre">:</span></code> in the
example text above which is only there for document formatting purposes.</p>
<p>Now, if you run the script you will see all of the log messages from both the
echo client and server applications.  You may see that this can be very useful
in debugging problems.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.406s<span class="o">)</span>
UdpEchoServerApplication:UdpEchoServer<span class="o">()</span>
UdpEchoClientApplication:UdpEchoClient<span class="o">()</span>
UdpEchoClientApplication:SetDataSize<span class="o">(</span><span class="m">1024</span><span class="o">)</span>
UdpEchoServerApplication:StartApplication<span class="o">()</span>
UdpEchoClientApplication:StartApplication<span class="o">()</span>
UdpEchoClientApplication:ScheduleTransmit<span class="o">()</span>
UdpEchoClientApplication:Send<span class="o">()</span>
UdpEchoClientApplication:Send<span class="o">()</span>: Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
UdpEchoServerApplication:HandleRead<span class="o">()</span>: Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
UdpEchoServerApplication:HandleRead<span class="o">()</span>: Echoing packet
UdpEchoClientApplication:HandleRead<span class="o">(</span>0x624920, 0x625160<span class="o">)</span>
UdpEchoClientApplication:HandleRead<span class="o">()</span>: Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
UdpEchoServerApplication:StopApplication<span class="o">()</span>
UdpEchoClientApplication:StopApplication<span class="o">()</span>
UdpEchoClientApplication:DoDispose<span class="o">()</span>
UdpEchoServerApplication:DoDispose<span class="o">()</span>
UdpEchoClientApplication:~UdpEchoClient<span class="o">()</span>
UdpEchoServerApplication:~UdpEchoServer<span class="o">()</span>
</pre></div>
</div>
<p>It is also sometimes useful to be able to see the simulation time at which a
log message is generated.  You can do this by ORing in the prefix_time bit.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">export</span> <span class="s1">'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time:</span>
<span class="s1">               UdpEchoServerApplication=level_all|prefix_func|prefix_time'</span>
</pre></div>
</div>
<p>Again, you will have to remove the newline above.  If you run the script now,
you should see the following output:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.418s<span class="o">)</span>
0s UdpEchoServerApplication:UdpEchoServer<span class="o">()</span>
0s UdpEchoClientApplication:UdpEchoClient<span class="o">()</span>
0s UdpEchoClientApplication:SetDataSize<span class="o">(</span><span class="m">1024</span><span class="o">)</span>
1s UdpEchoServerApplication:StartApplication<span class="o">()</span>
2s UdpEchoClientApplication:StartApplication<span class="o">()</span>
2s UdpEchoClientApplication:ScheduleTransmit<span class="o">()</span>
2s UdpEchoClientApplication:Send<span class="o">()</span>
2s UdpEchoClientApplication:Send<span class="o">()</span>: Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
<span class="m">2</span>.00369s UdpEchoServerApplication:HandleRead<span class="o">()</span>: Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
<span class="m">2</span>.00369s UdpEchoServerApplication:HandleRead<span class="o">()</span>: Echoing packet
<span class="m">2</span>.00737s UdpEchoClientApplication:HandleRead<span class="o">(</span>0x624290, 0x624ad0<span class="o">)</span>
<span class="m">2</span>.00737s UdpEchoClientApplication:HandleRead<span class="o">()</span>: Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
10s UdpEchoServerApplication:StopApplication<span class="o">()</span>
10s UdpEchoClientApplication:StopApplication<span class="o">()</span>
UdpEchoClientApplication:DoDispose<span class="o">()</span>
UdpEchoServerApplication:DoDispose<span class="o">()</span>
UdpEchoClientApplication:~UdpEchoClient<span class="o">()</span>
UdpEchoServerApplication:~UdpEchoServer<span class="o">()</span>
</pre></div>
</div>
<p>You can see that the constructor for the UdpEchoServer was called at a
simulation time of 0 seconds.  This is actually happening before the
simulation starts, but the time is displayed as zero seconds.  The same is true
for the UdpEchoClient constructor message.</p>
<p>Recall that the <code class="docutils literal notranslate"><span class="pre">scratch/first.cc</span></code> script started the echo server
application at one second into the simulation.  You can now see that the
<code class="docutils literal notranslate"><span class="pre">StartApplication</span></code> method of the server is, in fact, called at one second.
You can also see that the echo client application is started at a simulation
time of two seconds as we requested in the script.</p>
<p>You can now follow the progress of the simulation from the
<code class="docutils literal notranslate"><span class="pre">ScheduleTransmit</span></code> call in the client that calls <code class="docutils literal notranslate"><span class="pre">Send</span></code> to the
<code class="docutils literal notranslate"><span class="pre">HandleRead</span></code> callback in the echo server application.  Note that the
elapsed time for the packet to be sent across the point-to-point link is 3.69
milliseconds.  You see the echo server logging a message telling you that it
has echoed the packet and then, after another channel delay, you see the echo
client receive the echoed packet in its <code class="docutils literal notranslate"><span class="pre">HandleRead</span></code> method.</p>
<p>There is a lot that is happening under the covers in this simulation that you
are not seeing as well.  You can very easily follow the entire process by
turning on all of the logging components in the system.  Try setting the
<code class="docutils literal notranslate"><span class="pre">NS_LOG</span></code> variable to the following,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">export</span> <span class="s1">'NS_LOG=*=level_all|prefix_func|prefix_time'</span>
</pre></div>
</div>
<p>The asterisk above is the logging component wildcard.  This will turn on all
of the logging in all of the components used in the simulation.  I won’t
reproduce the output here (as of this writing it produces 1265 lines of output
for the single packet echo) but you can redirect this information into a file
and look through it with your favorite editor if you like,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run scratch/myfirst &gt; log.out <span class="m">2</span>&gt;<span class="p">&amp;</span><span class="m">1</span>
</pre></div>
</div>
<p>I personally use this extremely verbose version of logging when I am presented
with a problem and I have no idea where things are going wrong.  I can follow the
progress of the code quite easily without having to set breakpoints and step
through code in a debugger.  I can just edit up the output in my favorite editor
and search around for things I expect, and see things happening that I don’t
expect.  When I have a general idea about what is going wrong, I transition into
a debugger for a fine-grained examination of the problem.  This kind of output
can be especially useful when your script does something completely unexpected.
If you are stepping using a debugger you may miss an unexpected excursion
completely.  Logging the excursion makes it quickly visible.</p>
</div>
<div class="section" id="adding-logging-to-your-code">
<h3>Adding Logging to your Code<a class="headerlink" href="#adding-logging-to-your-code" title="Permalink to this headline">¶</a></h3>
<p>You can add new logging to your simulations by making calls to the log
component via several macros.  Let’s do so in the <code class="docutils literal notranslate"><span class="pre">myfirst.cc</span></code> script we
have in the <code class="docutils literal notranslate"><span class="pre">scratch</span></code> directory.</p>
<p>Recall that we have defined a logging component in that script:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">NS_LOG_COMPONENT_DEFINE</span> <span class="p">(</span><span class="s">"FirstScriptExample"</span><span class="p">);</span>
</pre></div>
</div>
<p>You now know that you can enable all of the logging for this component by
setting the <code class="docutils literal notranslate"><span class="pre">NS_LOG</span></code> environment variable to the various levels.  Let’s
go ahead and add some logging to the script.  The macro used to add an
informational level log message is <code class="docutils literal notranslate"><span class="pre">NS_LOG_INFO</span></code>.  Go ahead and add one
(just before we start creating the nodes) that tells you that the script is
“Creating Topology.”  This is done as in this code snippet,</p>
<p>Open <code class="docutils literal notranslate"><span class="pre">scratch/myfirst.cc</span></code> in your favorite editor and add the line,</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">NS_LOG_INFO</span> <span class="p">(</span><span class="s">"Creating Topology"</span><span class="p">);</span>
</pre></div>
</div>
<p>right before the lines,</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">NodeContainer</span> <span class="n">nodes</span><span class="p">;</span>
<span class="n">nodes</span><span class="p">.</span><span class="n">Create</span> <span class="p">(</span><span class="mi">2</span><span class="p">);</span>
</pre></div>
</div>
<p>Now build the script using waf and clear the <code class="docutils literal notranslate"><span class="pre">NS_LOG</span></code> variable to turn
off the torrent of logging we previously enabled:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf
$ <span class="nb">export</span> <span class="nv">NS_LOG</span><span class="o">=</span>
</pre></div>
</div>
<p>Now, if you run the script,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run scratch/myfirst
</pre></div>
</div>
<p>you will <code class="docutils literal notranslate"><span class="pre">not</span></code> see your new message since its associated logging
component (<code class="docutils literal notranslate"><span class="pre">FirstScriptExample</span></code>) has not been enabled.  In order to see your
message you will have to enable the <code class="docutils literal notranslate"><span class="pre">FirstScriptExample</span></code> logging component
with a level greater than or equal to <code class="docutils literal notranslate"><span class="pre">NS_LOG_INFO</span></code>.  If you just want to
see this particular level of logging, you can enable it by,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">export</span> <span class="nv">NS_LOG</span><span class="o">=</span><span class="nv">FirstScriptExample</span><span class="o">=</span>info
</pre></div>
</div>
<p>If you now run the script you will see your new “Creating Topology” log
message,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.404s<span class="o">)</span>
Creating Topology
Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
</pre></div>
</div>
</div>
</div>
<div class="section" id="using-command-line-arguments">
<h2>Using Command Line Arguments<a class="headerlink" href="#using-command-line-arguments" title="Permalink to this headline">¶</a></h2>
<div class="section" id="overriding-default-attributes">
<span id="attribute"></span><h3>Overriding Default Attributes<a class="headerlink" href="#overriding-default-attributes" title="Permalink to this headline">¶</a></h3>
<p>Another way you can change how <em>ns-3</em> scripts behave without editing
and building is via <em>command line arguments.</em>  We provide a mechanism to
parse command line arguments and automatically set local and global variables
based on those arguments.</p>
<p>The first step in using the command line argument system is to declare the
command line parser.  This is done quite simply (in your main program) as
in the following code,</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span>
<span class="nf">main</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
  <span class="p">...</span>

  <span class="n">CommandLine</span> <span class="n">cmd</span><span class="p">;</span>
  <span class="n">cmd</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>

  <span class="p">...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>This simple two line snippet is actually very useful by itself.  It opens the
door to the <em>ns-3</em> global variable and <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> systems.  Go
ahead and add that two lines of code to the <code class="docutils literal notranslate"><span class="pre">scratch/myfirst.cc</span></code> script at
the start of <code class="docutils literal notranslate"><span class="pre">main</span></code>.  Go ahead and build the script and run it, but ask
the script for help in the following way,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst --PrintHelp"</span>
</pre></div>
</div>
<p>This will ask Waf to run the <code class="docutils literal notranslate"><span class="pre">scratch/myfirst</span></code> script and pass the command
line argument <code class="docutils literal notranslate"><span class="pre">--PrintHelp</span></code> to the script.  The quotes are required to
sort out which program gets which argument.  The command line parser will
now see the <code class="docutils literal notranslate"><span class="pre">--PrintHelp</span></code> argument and respond with,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.413s<span class="o">)</span>
TcpL4Protocol:TcpStateMachine<span class="o">()</span>
CommandLine:HandleArgument<span class="o">()</span>: Handle arg <span class="nv">name</span><span class="o">=</span>PrintHelp <span class="nv">value</span><span class="o">=</span>
--PrintHelp: Print this <span class="nb">help</span> message.
--PrintGroups: Print the list of groups.
--PrintTypeIds: Print all TypeIds.
--PrintGroup<span class="o">=[</span>group<span class="o">]</span>: Print all TypeIds of group.
--PrintAttributes<span class="o">=[</span>typeid<span class="o">]</span>: Print all attributes of typeid.
--PrintGlobals: Print the list of globals.
</pre></div>
</div>
<p>Let’s focus on the <code class="docutils literal notranslate"><span class="pre">--PrintAttributes</span></code> option.  We have already hinted
at the <em>ns-3</em> <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> system while walking through the
<code class="docutils literal notranslate"><span class="pre">first.cc</span></code> script.  We looked at the following lines of code,</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">PointToPointHelper</span> <span class="n">pointToPoint</span><span class="p">;</span>
<span class="n">pointToPoint</span><span class="p">.</span><span class="n">SetDeviceAttribute</span> <span class="p">(</span><span class="s">"DataRate"</span><span class="p">,</span> <span class="n">StringValue</span> <span class="p">(</span><span class="s">"5Mbps"</span><span class="p">));</span>
<span class="n">pointToPoint</span><span class="p">.</span><span class="n">SetChannelAttribute</span> <span class="p">(</span><span class="s">"Delay"</span><span class="p">,</span> <span class="n">StringValue</span> <span class="p">(</span><span class="s">"2ms"</span><span class="p">));</span>
</pre></div>
</div>
<p>and mentioned that <code class="docutils literal notranslate"><span class="pre">DataRate</span></code> was actually an <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> of the
<code class="docutils literal notranslate"><span class="pre">PointToPointNetDevice</span></code>.  Let’s use the command line argument parser
to take a look at the <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> of the PointToPointNetDevice.  The help
listing says that we should provide a <code class="docutils literal notranslate"><span class="pre">TypeId</span></code>.  This corresponds to the
class name of the class to which the <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> belong.  In this case it
will be <code class="docutils literal notranslate"><span class="pre">ns3::PointToPointNetDevice</span></code>.  Let’s go ahead and type in,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"</span>
</pre></div>
</div>
<p>The system will print out all of the <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> of this kind of net device.
Among the <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> you will see listed is,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>--ns3::PointToPointNetDevice::DataRate<span class="o">=[</span>32768bps<span class="o">]</span>:
  The default data rate <span class="k">for</span> point to point links
</pre></div>
</div>
<p>This is the default value that will be used when a <code class="docutils literal notranslate"><span class="pre">PointToPointNetDevice</span></code>
is created in the system.  We overrode this default with the <code class="docutils literal notranslate"><span class="pre">Attribute</span></code>
setting in the <code class="docutils literal notranslate"><span class="pre">PointToPointHelper</span></code> above.  Let’s use the default values
for the point-to-point devices and channels by deleting the
<code class="docutils literal notranslate"><span class="pre">SetDeviceAttribute</span></code> call and the <code class="docutils literal notranslate"><span class="pre">SetChannelAttribute</span></code> call from
the <code class="docutils literal notranslate"><span class="pre">myfirst.cc</span></code> we have in the scratch directory.</p>
<p>Your script should now just declare the <code class="docutils literal notranslate"><span class="pre">PointToPointHelper</span></code> and not do
any <code class="docutils literal notranslate"><span class="pre">set</span></code> operations as in the following example,</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="p">...</span>

<span class="n">NodeContainer</span> <span class="n">nodes</span><span class="p">;</span>
<span class="n">nodes</span><span class="p">.</span><span class="n">Create</span> <span class="p">(</span><span class="mi">2</span><span class="p">);</span>

<span class="n">PointToPointHelper</span> <span class="n">pointToPoint</span><span class="p">;</span>

<span class="n">NetDeviceContainer</span> <span class="n">devices</span><span class="p">;</span>
<span class="n">devices</span> <span class="o">=</span> <span class="n">pointToPoint</span><span class="p">.</span><span class="n">Install</span> <span class="p">(</span><span class="n">nodes</span><span class="p">);</span>

<span class="p">...</span>
</pre></div>
</div>
<p>Go ahead and build the new script with Waf (<code class="docutils literal notranslate"><span class="pre">./waf</span></code>) and let’s go back
and enable some logging from the UDP echo server application and turn on the
time prefix.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">export</span> <span class="s1">'NS_LOG=UdpEchoServerApplication=level_all|prefix_time'</span>
</pre></div>
</div>
<p>If you run the script, you should now see the following output,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.405s<span class="o">)</span>
0s UdpEchoServerApplication:UdpEchoServer<span class="o">()</span>
1s UdpEchoServerApplication:StartApplication<span class="o">()</span>
Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
<span class="m">2</span>.25732s Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
<span class="m">2</span>.25732s Echoing packet
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
10s UdpEchoServerApplication:StopApplication<span class="o">()</span>
UdpEchoServerApplication:DoDispose<span class="o">()</span>
UdpEchoServerApplication:~UdpEchoServer<span class="o">()</span>
</pre></div>
</div>
<p>Recall that the last time we looked at the simulation time at which the packet
was received by the echo server, it was at 2.00369 seconds.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="m">2</span>.00369s UdpEchoServerApplication:HandleRead<span class="o">()</span>: Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
</pre></div>
</div>
<p>Now it is receiving the packet at 2.25732 seconds.  This is because we just dropped
the data rate of the <code class="docutils literal notranslate"><span class="pre">PointToPointNetDevice</span></code> down to its default of
32768 bits per second from five megabits per second.</p>
<p>If we were to provide a new <code class="docutils literal notranslate"><span class="pre">DataRate</span></code> using the command line, we could
speed our simulation up again.  We do this in the following way, according to
the formula implied by the help item:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"</span>
</pre></div>
</div>
<p>This will set the default value of the <code class="docutils literal notranslate"><span class="pre">DataRate</span></code> <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> back to
five megabits per second.  Are you surprised by the result?  It turns out that
in order to get the original behavior of the script back, we will have to set
the speed-of-light delay of the channel as well.  We can ask the command line
system to print out the <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> of the channel just like we did for
the net device:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"</span>
</pre></div>
</div>
<p>We discover the <code class="docutils literal notranslate"><span class="pre">Delay</span></code> <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> of the channel is set in the following
way:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>--ns3::PointToPointChannel::Delay<span class="o">=[</span>0ns<span class="o">]</span>:
  Transmission delay through the channel
</pre></div>
</div>
<p>We can then set both of these default values through the command line system,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst</span>
<span class="s2">  --ns3::PointToPointNetDevice::DataRate=5Mbps</span>
<span class="s2">  --ns3::PointToPointChannel::Delay=2ms"</span>
</pre></div>
</div>
<p>in which case we recover the timing we had when we explicitly set the
<code class="docutils literal notranslate"><span class="pre">DataRate</span></code> and <code class="docutils literal notranslate"><span class="pre">Delay</span></code> in the script:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.417s<span class="o">)</span>
0s UdpEchoServerApplication:UdpEchoServer<span class="o">()</span>
1s UdpEchoServerApplication:StartApplication<span class="o">()</span>
Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
<span class="m">2</span>.00369s Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
<span class="m">2</span>.00369s Echoing packet
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
10s UdpEchoServerApplication:StopApplication<span class="o">()</span>
UdpEchoServerApplication:DoDispose<span class="o">()</span>
UdpEchoServerApplication:~UdpEchoServer<span class="o">()</span>
</pre></div>
</div>
<p>Note that the packet is again received by the server at 2.00369 seconds.  We
could actually set any of the <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> used in the script in this way.
In particular we could set the <code class="docutils literal notranslate"><span class="pre">UdpEchoClient</span> <span class="pre">Attribute</span> <span class="pre">MaxPackets</span></code>
to some other value than one.</p>
<p>How would you go about that?  Give it a try.  Remember you have to comment
out the place we override the default <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> and explicitly set
<code class="docutils literal notranslate"><span class="pre">MaxPackets</span></code> in the script.  Then you have to rebuild the script.  You
will also have to find the syntax for actually setting the new default attribute
value using the command line help facility.  Once you have this figured out
you should be able to control the number of packets echoed from the command
line.  Since we’re nice folks, we’ll tell you that your command line should
end up looking something like,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst</span>
<span class="s2">  --ns3::PointToPointNetDevice::DataRate=5Mbps</span>
<span class="s2">  --ns3::PointToPointChannel::Delay=2ms</span>
<span class="s2">  --ns3::UdpEchoClient::MaxPackets=2"</span>
</pre></div>
</div>
<p>A natural question to arise at this point is how to learn about the existence
of all of these attributes.  Again, the command line help facility has
a feature for this.  If we ask for command line help we should see:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst --PrintHelp"</span>
myfirst <span class="o">[</span>Program Arguments<span class="o">]</span> <span class="o">[</span>General Arguments<span class="o">]</span>

General Arguments:
  --PrintGlobals:              Print the list of globals.
  --PrintGroups:               Print the list of groups.
  --PrintGroup<span class="o">=[</span>group<span class="o">]</span>:        Print all TypeIds of group.
  --PrintTypeIds:              Print all TypeIds.
  --PrintAttributes<span class="o">=[</span>typeid<span class="o">]</span>:  Print all attributes of typeid.
  --PrintHelp:                 Print this <span class="nb">help</span> message.
</pre></div>
</div>
<p>If you select the “PrintGroups” argument, you should see a list of all
registered TypeId groups.  The group names are aligned with the module names
in the source directory (although with a leading capital letter).  Printing
out all of the information at once would be too much, so a further filter
is available to print information on a per-group basis.   So, focusing
again on the point-to-point module:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>./waf --run <span class="s2">"scratch/myfirst --PrintGroup=PointToPoint"</span>
TypeIds in group PointToPoint:
  ns3::PointToPointChannel
  ns3::PointToPointNetDevice
  ns3::PointToPointRemoteChannel
  ns3::PppHeader
</pre></div>
</div>
<p>and from here, one can find the possible TypeId names to search for
attributes, such as in the <code class="docutils literal notranslate"><span class="pre">--PrintAttributes=ns3::PointToPointChannel</span></code>
example shown above.</p>
<p>Another way to find out about attributes is through the ns-3 Doxygen; there
is a page that lists out all of the registered attributes in the simulator.</p>
</div>
<div class="section" id="hooking-your-own-values">
<h3>Hooking Your Own Values<a class="headerlink" href="#hooking-your-own-values" title="Permalink to this headline">¶</a></h3>
<p>You can also add your own hooks to the command line system.  This is done
quite simply by using the <code class="docutils literal notranslate"><span class="pre">AddValue</span></code> method to the command line parser.</p>
<p>Let’s use this facility to specify the number of packets to echo in a
completely different way.  Let’s add a local variable called <code class="docutils literal notranslate"><span class="pre">nPackets</span></code>
to the <code class="docutils literal notranslate"><span class="pre">main</span></code> function.  We’ll initialize it to one to match our previous
default behavior.  To allow the command line parser to change this value, we
need to hook the value into the parser.  We do this by adding a call to
<code class="docutils literal notranslate"><span class="pre">AddValue</span></code>.  Go ahead and change the <code class="docutils literal notranslate"><span class="pre">scratch/myfirst.cc</span></code> script to
start with the following code,</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="kt">int</span>
<span class="nf">main</span> <span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
<span class="p">{</span>
  <span class="kt">uint32_t</span> <span class="n">nPackets</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>

  <span class="n">CommandLine</span> <span class="n">cmd</span><span class="p">;</span>
  <span class="n">cmd</span><span class="p">.</span><span class="n">AddValue</span><span class="p">(</span><span class="s">"nPackets"</span><span class="p">,</span> <span class="s">"Number of packets to echo"</span><span class="p">,</span> <span class="n">nPackets</span><span class="p">);</span>
  <span class="n">cmd</span><span class="p">.</span><span class="n">Parse</span> <span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>

  <span class="p">...</span>
</pre></div>
</div>
<p>Scroll down to the point in the script where we set the <code class="docutils literal notranslate"><span class="pre">MaxPackets</span></code>
<code class="docutils literal notranslate"><span class="pre">Attribute</span></code> and change it so that it is set to the variable <code class="docutils literal notranslate"><span class="pre">nPackets</span></code>
instead of the constant <code class="docutils literal notranslate"><span class="pre">1</span></code> as is shown below.</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">echoClient</span><span class="p">.</span><span class="n">SetAttribute</span> <span class="p">(</span><span class="s">"MaxPackets"</span><span class="p">,</span> <span class="n">UintegerValue</span> <span class="p">(</span><span class="n">nPackets</span><span class="p">));</span>
</pre></div>
</div>
<p>Now if you run the script and provide the <code class="docutils literal notranslate"><span class="pre">--PrintHelp</span></code> argument, you
should see your new <code class="docutils literal notranslate"><span class="pre">User</span> <span class="pre">Argument</span></code> listed in the help display.</p>
<p>Try,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst --PrintHelp"</span>
</pre></div>
</div>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.403s<span class="o">)</span>
--PrintHelp: Print this <span class="nb">help</span> message.
--PrintGroups: Print the list of groups.
--PrintTypeIds: Print all TypeIds.
--PrintGroup<span class="o">=[</span>group<span class="o">]</span>: Print all TypeIds of group.
--PrintAttributes<span class="o">=[</span>typeid<span class="o">]</span>: Print all attributes of typeid.
--PrintGlobals: Print the list of globals.
User Arguments:
    --nPackets: Number of packets to <span class="nb">echo</span>
</pre></div>
</div>
<p>If you want to specify the number of packets to echo, you can now do so by
setting the <code class="docutils literal notranslate"><span class="pre">--nPackets</span></code> argument in the command line,</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run <span class="s2">"scratch/myfirst --nPackets=2"</span>
</pre></div>
</div>
<p>You should now see</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Waf: Entering directory <span class="sb">`</span>/home/craigdo/repos/ns-3-allinone/ns-3-dev/build<span class="s1">'</span>
<span class="s1">Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'</span>
<span class="s1">'build'</span> finished successfully <span class="o">(</span><span class="m">0</span>.404s<span class="o">)</span>
0s UdpEchoServerApplication:UdpEchoServer<span class="o">()</span>
1s UdpEchoServerApplication:StartApplication<span class="o">()</span>
Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
<span class="m">2</span>.25732s Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
<span class="m">2</span>.25732s Echoing packet
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
Sent <span class="m">1024</span> bytes to <span class="m">10</span>.1.1.2
<span class="m">3</span>.25732s Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.1
<span class="m">3</span>.25732s Echoing packet
Received <span class="m">1024</span> bytes from <span class="m">10</span>.1.1.2
10s UdpEchoServerApplication:StopApplication<span class="o">()</span>
UdpEchoServerApplication:DoDispose<span class="o">()</span>
UdpEchoServerApplication:~UdpEchoServer<span class="o">()</span>
</pre></div>
</div>
<p>You have now echoed two packets.  Pretty easy, isn’t it?</p>
<p>You can see that if you are an <em>ns-3</em> user, you can use the command
line argument system to control global values and <code class="docutils literal notranslate"><span class="pre">Attributes</span></code>.  If you are
a model author, you can add new <code class="docutils literal notranslate"><span class="pre">Attributes</span></code> to your <code class="docutils literal notranslate"><span class="pre">Objects</span></code> and
they will automatically be available for setting by your users through the
command line system.  If you are a script author, you can add new variables to
your scripts and hook them into the command line system quite painlessly.</p>
</div>
</div>
<div class="section" id="using-the-tracing-system">
<span id="usingtracingsystem"></span><h2>Using the Tracing System<a class="headerlink" href="#using-the-tracing-system" title="Permalink to this headline">¶</a></h2>
<p>The whole point of simulation is to generate output for further study, and
the <em>ns-3</em> tracing system is a primary mechanism for this.  Since
<em>ns-3</em> is a C++ program, standard facilities for generating output
from C++ programs could be used:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span>
<span class="p">...</span>
<span class="kt">int</span> <span class="n">main</span> <span class="p">()</span>
<span class="p">{</span>
  <span class="p">...</span>
  <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">"The value of x is "</span> <span class="o">&lt;&lt;</span> <span class="n">x</span> <span class="o">&lt;&lt;</span> <span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
  <span class="p">...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>You could even use the logging module to add a little structure to your
solution.  There are many well-known problems generated by such approaches
and so we have provided a generic event tracing subsystem to address the
issues we thought were important.</p>
<p>The basic goals of the <em>ns-3</em> tracing system are:</p>
<ul class="simple">
<li>For basic tasks, the tracing system should allow the user to generate
standard tracing for popular tracing sources, and to customize which objects
generate the tracing;</li>
<li>Intermediate users must be able to extend the tracing system to modify
the output format generated, or to insert new tracing sources, without
modifying the core of the simulator;</li>
<li>Advanced users can modify the simulator core to add new tracing sources
and sinks.</li>
</ul>
<p>The <em>ns-3</em> tracing system is built on the concepts of independent
tracing sources and tracing sinks, and a uniform mechanism for connecting
sources to sinks.  Trace sources are entities that can signal events that
happen in a simulation and provide access to interesting underlying data.
For example, a trace source could indicate when a packet is received by a net
device and provide access to the packet contents for interested trace sinks.</p>
<p>Trace sources are not useful by themselves, they must be “connected” to
other pieces of code that actually do something useful with the information
provided by the sink.  Trace sinks are consumers of the events and data
provided by the trace sources.  For example, one could create a trace sink
that would (when connected to the trace source of the previous example) print
out interesting parts of the received packet.</p>
<p>The rationale for this explicit division is to allow users to attach new
types of sinks to existing tracing sources, without requiring editing and
recompilation of the core of the simulator.  Thus, in the example above,
a user could define a new tracing sink in her script and attach it to an
existing tracing source defined in the simulation core by editing only the
user script.</p>
<p>In this tutorial, we will walk through some pre-defined sources and sinks and
show how they may be customized with little user effort.  See the ns-3 manual
or how-to sections for information on advanced tracing configuration including
extending the tracing namespace and creating new tracing sources.</p>
<div class="section" id="ascii-tracing">
<h3>ASCII Tracing<a class="headerlink" href="#ascii-tracing" title="Permalink to this headline">¶</a></h3>
<p><em>ns-3</em> provides helper functionality that wraps the low-level tracing
system to help you with the details involved in configuring some easily
understood packet traces.  If you enable this functionality, you will see
output in a ASCII files — thus the name.  For those familiar with
<em>ns-2</em> output, this type of trace is analogous to the <code class="docutils literal notranslate"><span class="pre">out.tr</span></code>
generated by many scripts.</p>
<p>Let’s just jump right in and add some ASCII tracing output to our
<code class="docutils literal notranslate"><span class="pre">scratch/myfirst.cc</span></code> script.  Right before the call to
<code class="docutils literal notranslate"><span class="pre">Simulator::Run</span> <span class="pre">()</span></code>, add the following lines of code:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">AsciiTraceHelper</span> <span class="n">ascii</span><span class="p">;</span>
<span class="n">pointToPoint</span><span class="p">.</span><span class="n">EnableAsciiAll</span> <span class="p">(</span><span class="n">ascii</span><span class="p">.</span><span class="n">CreateFileStream</span> <span class="p">(</span><span class="s">"myfirst.tr"</span><span class="p">));</span>
</pre></div>
</div>
<p>Like in many other <em>ns-3</em> idioms, this code uses a  helper object to
help create ASCII traces.  The second line contains two nested method calls.
The “inside” method, <code class="docutils literal notranslate"><span class="pre">CreateFileStream()</span></code> uses an unnamed object idiom
to create a file stream object on the stack (without an object  name) and pass
it down to the called method.  We’ll go into this more in the future, but all
you have to know at this point is that you are creating an object representing
a file named “myfirst.tr” and passing it into <code class="docutils literal notranslate"><span class="pre">ns-3</span></code>.  You are telling
<code class="docutils literal notranslate"><span class="pre">ns-3</span></code> to deal with the lifetime issues of the created object and also to
deal with problems caused by a little-known (intentional) limitation of C++
ofstream objects relating to copy constructors.</p>
<p>The outside call, to <code class="docutils literal notranslate"><span class="pre">EnableAsciiAll()</span></code>, tells the helper that you
want to enable ASCII tracing on all point-to-point devices in your simulation;
and you want the (provided) trace sinks to write out information about packet
movement in ASCII format.</p>
<p>For those familiar with <em>ns-2</em>, the traced events are equivalent to
the popular trace points that log “+”, “-“, “d”, and “r” events.</p>
<p>You can now build the script and run it from the command line:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run scratch/myfirst
</pre></div>
</div>
<p>Just as you have seen many times before, you will see some messages from Waf and then
“‘build’ finished successfully” with some number of messages from
the running program.</p>
<p>When it ran, the program will have created a file named <code class="docutils literal notranslate"><span class="pre">myfirst.tr</span></code>.
Because of the way that Waf works, the file is not created in the local
directory, it is created at the top-level directory of the repository by
default.  If you want to control where the traces are saved you can use the
<code class="docutils literal notranslate"><span class="pre">--cwd</span></code> option of Waf to specify this.  We have not done so, thus we
need to change into the top level directory of our repo and take a look at
the ASCII trace file <code class="docutils literal notranslate"><span class="pre">myfirst.tr</span></code> in your favorite editor.</p>
<div class="section" id="parsing-ascii-traces">
<h4>Parsing Ascii Traces<a class="headerlink" href="#parsing-ascii-traces" title="Permalink to this headline">¶</a></h4>
<p>There’s a lot of information there in a pretty dense form, but the first thing
to notice is that there are a number of distinct lines in this file.  It may
be difficult to see this clearly unless you widen your window considerably.</p>
<p>Each line in the file corresponds to a <em>trace event</em>.  In this case
we are tracing events on the <em>transmit queue</em> present in every
point-to-point net device in the simulation.  The transmit queue is a queue
through which every packet destined for a point-to-point channel must pass.
Note that each line in the trace file begins with a lone character (has a
space after it).  This character will have the following meaning:</p>
<ul class="simple">
<li><code class="docutils literal notranslate"><span class="pre">+</span></code>: An enqueue operation occurred on the device queue;</li>
<li><code class="docutils literal notranslate"><span class="pre">-</span></code>: A dequeue operation occurred on the device queue;</li>
<li><code class="docutils literal notranslate"><span class="pre">d</span></code>: A packet was dropped, typically because the queue was full;</li>
<li><code class="docutils literal notranslate"><span class="pre">r</span></code>: A packet was received by the net device.</li>
</ul>
<p>Let’s take a more detailed view of the first line in the trace file.  I’ll
break it down into sections (indented for clarity) with a reference
number on the left side:</p>
<div class="highlight-text notranslate"><table class="highlighttable"><tbody><tr><td class="linenos"><div class="linenodiv"><pre> 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11</pre></div></td><td class="code"><div class="highlight"><pre><span></span>+
2
/NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue
ns3::PppHeader (
  Point-to-Point Protocol: IP (0x0021))
  ns3::Ipv4Header (
    tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
    length: 1052 10.1.1.1 &gt; 10.1.1.2)
    ns3::UdpHeader (
      length: 1032 49153 &gt; 9)
      Payload (size=1024)
</pre></div>
</td></tr></tbody></table></div>
<p>The first section of this expanded trace event (reference number 0) is the
operation.  We have a <code class="docutils literal notranslate"><span class="pre">+</span></code> character, so this corresponds to an
<em>enqueue</em> operation on the transmit queue.  The second section (reference 1)
is the simulation time expressed in seconds.  You may recall that we asked the
<code class="docutils literal notranslate"><span class="pre">UdpEchoClientApplication</span></code> to start sending packets at two seconds.  Here
we see confirmation that this is, indeed, happening.</p>
<p>The next section of the example trace (reference 2) tell us which trace source
originated this event (expressed in the tracing namespace).  You can think
of the tracing namespace somewhat like you would a filesystem namespace.  The
root of the namespace is the <code class="docutils literal notranslate"><span class="pre">NodeList</span></code>.  This corresponds to a container
managed in the <em>ns-3</em> core code that contains all of the nodes that are
created in a script.  Just as a filesystem may have directories under the
root, we may have node numbers in the <code class="docutils literal notranslate"><span class="pre">NodeList</span></code>.  The string
<code class="docutils literal notranslate"><span class="pre">/NodeList/0</span></code> therefore refers to the zeroth node in the <code class="docutils literal notranslate"><span class="pre">NodeList</span></code>
which we typically think of as “node 0”.  In each node there is a list of
devices that have been installed.  This list appears next in the namespace.
You can see that this trace event comes from <code class="docutils literal notranslate"><span class="pre">DeviceList/0</span></code> which is the
zeroth device installed in the node.</p>
<p>The next string, <code class="docutils literal notranslate"><span class="pre">$ns3::PointToPointNetDevice</span></code> tells you what kind of
device is in the zeroth position of the device list for node zero.
Recall that the operation <code class="docutils literal notranslate"><span class="pre">+</span></code> found at reference 00 meant that an enqueue
operation happened on the transmit queue of the device.  This is reflected in
the final segments of the “trace path” which are <code class="docutils literal notranslate"><span class="pre">TxQueue/Enqueue</span></code>.</p>
<p>The remaining sections in the trace should be fairly intuitive.  References 3-4
indicate that the packet is encapsulated in the point-to-point protocol.
References 5-7 show that the packet has an IP version four header and has
originated from IP address 10.1.1.1 and is destined for 10.1.1.2.  References
8-9 show that this packet has a UDP header and, finally, reference 10 shows
that the payload is the expected 1024 bytes.</p>
<p>The next line in the trace file shows the same packet being dequeued from the
transmit queue on the same node.</p>
<p>The Third line in the trace file shows the packet being received by the net
device on the node with the echo server. I have reproduced that event below.</p>
<div class="highlight-text notranslate"><table class="highlighttable"><tbody><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8
9</pre></div></td><td class="code"><div class="highlight"><pre><span></span>r
2.25732
/NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx
  ns3::Ipv4Header (
    tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none]
    length: 1052 10.1.1.1 &gt; 10.1.1.2)
    ns3::UdpHeader (
      length: 1032 49153 &gt; 9)
      Payload (size=1024)
</pre></div>
</td></tr></tbody></table></div>
<p>Notice that the trace operation is now <code class="docutils literal notranslate"><span class="pre">r</span></code> and the simulation time has
increased to 2.25732 seconds.  If you have been following the tutorial steps
closely this means that you have left the <code class="docutils literal notranslate"><span class="pre">DataRate</span></code> of the net devices
and the channel <code class="docutils literal notranslate"><span class="pre">Delay</span></code> set to their default values.  This time should
be familiar as you have seen it before in a previous section.</p>
<p>The trace source namespace entry (reference 02) has changed to reflect that
this event is coming from node 1 (<code class="docutils literal notranslate"><span class="pre">/NodeList/1</span></code>) and the packet reception
trace source (<code class="docutils literal notranslate"><span class="pre">/MacRx</span></code>).  It should be quite easy for you to follow the
progress of the packet through the topology by looking at the rest of the
traces in the file.</p>
</div>
</div>
<div class="section" id="pcap-tracing">
<h3>PCAP Tracing<a class="headerlink" href="#pcap-tracing" title="Permalink to this headline">¶</a></h3>
<p>The <em>ns-3</em> device helpers can also be used to create trace files in the
<code class="docutils literal notranslate"><span class="pre">.pcap</span></code> format.  The acronym pcap (usually written in lower case) stands
for packet capture, and is actually an API that includes the
definition of a <code class="docutils literal notranslate"><span class="pre">.pcap</span></code> file format.  The most popular program that can
read and display this format is Wireshark (formerly called Ethereal).
However, there are many traffic trace analyzers that use this packet format.
We encourage users to exploit the many tools available for analyzing pcap
traces.  In this tutorial, we concentrate on viewing pcap traces with tcpdump.</p>
<p>The code used to enable pcap tracing is a one-liner.</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">pointToPoint</span><span class="p">.</span><span class="n">EnablePcapAll</span> <span class="p">(</span><span class="s">"myfirst"</span><span class="p">);</span>
</pre></div>
</div>
<p>Go ahead and insert this line of code after the ASCII tracing code we just
added to <code class="docutils literal notranslate"><span class="pre">scratch/myfirst.cc</span></code>.  Notice that we only passed the string
“myfirst,” and not “myfirst.pcap” or something similar.  This is because the
parameter is a prefix, not a complete file name.  The helper will actually
create a trace file for every point-to-point device in the simulation.  The
file names will be built using the prefix, the node number, the device number
and a “.pcap” suffix.</p>
<p>In our example script, we will eventually see files named “myfirst-0-0.pcap”
and “myfirst-1-0.pcap” which are the pcap traces for node 0-device 0 and
node 1-device 0, respectively.</p>
<p>Once you have added the line of code to enable pcap tracing, you can run the
script in the usual way:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ ./waf --run scratch/myfirst
</pre></div>
</div>
<p>If you look at the top level directory of your distribution, you should now
see three log files:  <code class="docutils literal notranslate"><span class="pre">myfirst.tr</span></code> is the ASCII trace file we have
previously examined.  <code class="docutils literal notranslate"><span class="pre">myfirst-0-0.pcap</span></code> and <code class="docutils literal notranslate"><span class="pre">myfirst-1-0.pcap</span></code>
are the new pcap files we just generated.</p>
<div class="section" id="reading-output-with-tcpdump">
<h4>Reading output with tcpdump<a class="headerlink" href="#reading-output-with-tcpdump" title="Permalink to this headline">¶</a></h4>
<p>The easiest thing to do at this point will be to use <code class="docutils literal notranslate"><span class="pre">tcpdump</span></code> to look
at the <code class="docutils literal notranslate"><span class="pre">pcap</span></code> files.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>$ tcpdump -nn -tt -r myfirst-0-0.pcap
reading from file myfirst-0-0.pcap, link-type PPP <span class="o">(</span>PPP<span class="o">)</span>
<span class="m">2</span>.000000 IP <span class="m">10</span>.1.1.1.49153 &gt; <span class="m">10</span>.1.1.2.9: UDP, length <span class="m">1024</span>
<span class="m">2</span>.514648 IP <span class="m">10</span>.1.1.2.9 &gt; <span class="m">10</span>.1.1.1.49153: UDP, length <span class="m">1024</span>

tcpdump -nn -tt -r myfirst-1-0.pcap
reading from file myfirst-1-0.pcap, link-type PPP <span class="o">(</span>PPP<span class="o">)</span>
<span class="m">2</span>.257324 IP <span class="m">10</span>.1.1.1.49153 &gt; <span class="m">10</span>.1.1.2.9: UDP, length <span class="m">1024</span>
<span class="m">2</span>.257324 IP <span class="m">10</span>.1.1.2.9 &gt; <span class="m">10</span>.1.1.1.49153: UDP, length <span class="m">1024</span>
</pre></div>
</div>
<p>You can see in the dump of <code class="docutils literal notranslate"><span class="pre">myfirst-0-0.pcap</span></code> (the client device) that the
echo packet is sent at 2 seconds into the simulation.  If you look at the
second dump (<code class="docutils literal notranslate"><span class="pre">myfirst-1-0.pcap</span></code>) you can see that packet being received
at 2.257324 seconds.  You see the packet being echoed back at 2.257324 seconds
in the second dump, and finally, you see the packet being received back at
the client in the first dump at 2.514648 seconds.</p>
</div>
<div class="section" id="reading-output-with-wireshark">
<h4>Reading output with Wireshark<a class="headerlink" href="#reading-output-with-wireshark" title="Permalink to this headline">¶</a></h4>
<p>If you are unfamiliar with Wireshark, there is a web site available from which
you can download programs and documentation:  <a class="reference external" href="http://www.wireshark.org/">http://www.wireshark.org/</a>.</p>
<p>Wireshark is a graphical user interface which can be used for displaying these
trace files.  If you have Wireshark available, you can open each of the trace
files and display the contents as if you had captured the packets using a
<em>packet sniffer</em>.</p>
</div>
</div>
</div>
</div>


          </div>